using System.Text;
using System.Text.RegularExpressions;

namespace Sage.Http.Utilities
{
    /// <summary>
    /// HTTP相关的通用工具方法
    /// </summary>
    public static class HttpUtilities
    {
        /// <summary>
        /// 根据文件扩展名获取MIME类型
        /// </summary>
        /// <param name="extension">文件扩展名（包含或不包含前导点）</param>
        /// <returns>MIME类型，如果未知则返回application/octet-stream</returns>
        public static string GetMimeTypeForFileExtension(string extension)
        {
            if (string.IsNullOrEmpty(extension))
                return "application/octet-stream";

            // 确保扩展名以点开头
            if (!extension.StartsWith('.'))
                extension = "." + extension;

            return extension.ToLowerInvariant() switch
            {
                ".jpg" or ".jpeg" => "image/jpeg",
                ".png" => "image/png",
                ".gif" => "image/gif",
                ".bmp" => "image/bmp",
                ".webp" => "image/webp",
                ".svg" => "image/svg+xml",
                ".ico" => "image/x-icon",
                
                ".txt" => "text/plain",
                ".html" or ".htm" => "text/html",
                ".css" => "text/css",
                ".csv" => "text/csv",
                
                ".js" => "application/javascript",
                ".json" => "application/json",
                ".xml" => "application/xml",
                ".pdf" => "application/pdf",
                ".zip" => "application/zip",
                ".gz" => "application/gzip",
                ".tar" => "application/x-tar",
                
                ".mp3" => "audio/mpeg",
                ".wav" => "audio/wav",
                ".ogg" => "audio/ogg",
                
                ".mp4" => "video/mp4",
                ".webm" => "video/webm",
                ".avi" => "video/x-msvideo",
                
                ".doc" or ".docx" => "application/msword",
                ".xls" or ".xlsx" => "application/vnd.ms-excel",
                ".ppt" or ".pptx" => "application/vnd.ms-powerpoint",
                
                _ => "application/octet-stream"  // 默认二进制流
            };
        }

        /// <summary>
        /// 构建包含查询参数的请求URL
        /// </summary>
        /// <param name="url">基础URL</param>
        /// <param name="queryParams">查询参数字典</param>
        /// <returns>带有查询参数的完整URL</returns>
        public static string BuildRequestUrl(string url, Dictionary<string, object>? queryParams)
        {
            ArgumentException.ThrowIfNullOrEmpty(url);

            if (queryParams == null || queryParams.Count == 0)
                return url;

            var query = new List<string>();

            // 遍历查询参数并进行URL编码
            foreach (var param in queryParams)
            {
                if (string.IsNullOrEmpty(param.Key))
                    continue; // 跳过空键

                var key = Uri.EscapeDataString(param.Key);
                var value = Uri.EscapeDataString(param.Value?.ToString() ?? string.Empty);
                query.Add($"{key}={value}");
            }

            // 组合查询字符串
            var queryString = string.Join("&", query);
            var separator = url.Contains('?') ? "&" : "?";
            var requestUrl = $"{url}{separator}{queryString}";

            return requestUrl;
        }

        /// <summary>
        /// 构建查询字符串
        /// </summary>
        /// <param name="parameters">参数字典</param>
        /// <returns>查询字符串（不包含前导?）</returns>
        public static string BuildQueryString(Dictionary<string, string> parameters)
        {
            if (parameters == null || parameters.Count == 0)
                return string.Empty;

            var queryParts = new List<string>(parameters.Count);
            foreach (var param in parameters)
            {
                if (string.IsNullOrEmpty(param.Key))
                    continue;

                var encodedKey = Uri.EscapeDataString(param.Key);
                var encodedValue = Uri.EscapeDataString(param.Value ?? string.Empty);
                queryParts.Add($"{encodedKey}={encodedValue}");
            }

            return string.Join("&", queryParts);
        }

        /// <summary>
        /// 解析查询字符串为字典
        /// </summary>
        /// <param name="queryString">查询字符串（可以包含前导?）</param>
        /// <returns>查询参数字典</returns>
        public static Dictionary<string, string> ParseQueryString(string queryString)
        {
            var result = new Dictionary<string, string>();

            if (string.IsNullOrEmpty(queryString))
                return result;

            // 移除前导?（如果存在）
            if (queryString.StartsWith('?'))
                queryString = queryString[1..];

            var parts = queryString.Split('&', StringSplitOptions.RemoveEmptyEntries);
            foreach (var part in parts)
            {
                var keyValue = part.Split('=', 2);
                if (keyValue.Length == 2)
                {
                    var key = Uri.UnescapeDataString(keyValue[0]);
                    var value = Uri.UnescapeDataString(keyValue[1]);
                    result[key] = value;
                }
                else if (keyValue.Length == 1)
                {
                    var key = Uri.UnescapeDataString(keyValue[0]);
                    result[key] = string.Empty;
                }
            }

            return result;
        }

        /// <summary>
        /// 向HTTP请求添加请求头
        /// </summary>
        /// <param name="request">HTTP请求消息</param>
        /// <param name="headers">请求头字典</param>
        public static void AddHeaders(HttpRequestMessage request, Dictionary<string, object>? headers)
        {
            ArgumentNullException.ThrowIfNull(request);

            if (headers == null || headers.Count == 0)
                return;

            // 遍历请求头并添加到请求中
            foreach (var header in headers)
            {
                if (string.IsNullOrEmpty(header.Key))
                    continue; // 跳过空键

                // 尝试添加请求头，如果失败则可能是内容头
                if (!request.Headers.TryAddWithoutValidation(header.Key, header.Value?.ToString()))
                {
                    // 如果需要添加内容头，并且请求已有内容，可以将其添加到请求的Content.Headers中
                    if (request.Content != null)
                    {
                        request.Content.Headers.TryAddWithoutValidation(header.Key, header.Value?.ToString());
                    }
                }
            }
        }

        /// <summary>
        /// 为请求设置超时时间
        /// </summary>
        /// <param name="request">HTTP请求消息</param>
        /// <param name="timeout">超时时间</param>
        public static void SetRequestTimeout(HttpRequestMessage request, TimeSpan timeout)
        {
            ArgumentNullException.ThrowIfNull(request);
            request.Options.Set(new HttpRequestOptionsKey<TimeSpan>("RequestTimeout"), timeout);
        }

        /// <summary>
        /// 提取数据内容，处理SSE格式和普通文本行
        /// </summary>
        /// <param name="line">原始行文本</param>
        /// <returns>数据内容</returns>
        public static string ExtractDataContent(string line)
        {
            // 检查是否为SSE格式的数据行
            if (line.StartsWith("data:", StringComparison.OrdinalIgnoreCase))
            {
                return line[5..].Trim();
            }

            return line;
        }

        /// <summary>
        /// 检查内容是否为二进制数据（基于MIME类型）
        /// </summary>
        /// <param name="content">HTTP内容</param>
        /// <returns>如果是二进制内容则返回true，否则返回false</returns>
        public static bool IsBinaryContent(HttpContent content)
        {
            if (content == null)
                return false;

            var contentType = content.Headers.ContentType?.MediaType;
            if (string.IsNullOrEmpty(contentType))
                return false;

            // 检查常见的二进制MIME类型
            return contentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase) ||
                   contentType.StartsWith("audio/", StringComparison.OrdinalIgnoreCase) ||
                   contentType.StartsWith("video/", StringComparison.OrdinalIgnoreCase) ||
                   contentType.StartsWith("application/octet-stream", StringComparison.OrdinalIgnoreCase) ||
                   contentType.StartsWith("application/pdf", StringComparison.OrdinalIgnoreCase) ||
                   contentType.StartsWith("application/zip", StringComparison.OrdinalIgnoreCase) ||
                   contentType.StartsWith("application/x-", StringComparison.OrdinalIgnoreCase);
        }

        /// <summary>
        /// 检查字符串是否为有效的JSON
        /// </summary>
        /// <param name="json">要检查的JSON字符串</param>
        /// <returns>如果是有效的JSON则返回true，否则返回false</returns>
        public static bool IsValidJson(string json)
        {
            if (string.IsNullOrWhiteSpace(json))
                return false;

            json = json.Trim();
            
            // 简单检查JSON格式
            return (json.StartsWith('{') && json.EndsWith('}')) || // 对象
                   (json.StartsWith('[') && json.EndsWith(']'));   // 数组
        }

        /// <summary>
        /// 截断文本，确保在字符边界处截断
        /// </summary>
        /// <param name="text">要截断的文本</param>
        /// <param name="maxLength">最大长度</param>
        /// <returns>截断后的文本</returns>
        public static string TruncateAtCharacterBoundary(string text, int maxLength)
        {
            if (string.IsNullOrEmpty(text) || text.Length <= maxLength)
                return text;

            // 确保在有效的UTF-8字符边界处截断
            var bytes = Encoding.UTF8.GetBytes(text);
            if (bytes.Length <= maxLength)
                return text;

            // 找到有效的UTF-8字符边界
            int validLength = maxLength;
            while (validLength > 0 && (bytes[validLength] & 0xC0) == 0x80)
            {
                validLength--;
            }

            return Encoding.UTF8.GetString(bytes, 0, validLength) + "...";
        }
    }
}